import React, { useContext, useState, useEffect, useRef } from 'react';
import { HotTable } from '@handsontable/react';
import Handsontable from 'handsontable';
import { StarTwoTone } from '@ant-design/icons';
import {
  Card,
  Button,
  Space,
  Upload,
  Input,
  Form,
  Table,
  Row,
  Col,
  Divider,
  message,
} from 'antd';
import { StatisticCard } from '@ant-design/pro-card';
import RcResizeObserver from 'rc-resize-observer';
import FileSaver from 'file-saver';

const EditableContext = React.createContext(null);
const EditableRow = ({ index, ...props }) => {
  const [form] = Form.useForm();
  return (
    <Form form={form} component={false}>
      <EditableContext.Provider value={form}>
        <tr {...props} />
      </EditableContext.Provider>
    </Form>
  );
};

const EditableCell = ({
  title,
  editable,
  children,
  dataIndex,
  record,
  handleSave,
  ...restProps
}) => {
  const [editing, setEditing] = useState(false);
  const inputRef = useRef(null);
  const form = useContext(EditableContext);
  useEffect(() => {
    if (editing) {
      inputRef.current.focus();
    }
  }, [editing]);

  const toggleEdit = () => {
    setEditing(!editing);
    form.setFieldsValue({
      [dataIndex]: record[dataIndex],
    });
  };

  const save = async () => {
    try {
      const values = await form.validateFields();
      toggleEdit();
      handleSave({ ...record, ...values });
    } catch (errInfo) {
      message.error('Save failed:', errInfo);
    }
  };

  let childNode = children;

  if (editable) {
    childNode = editing ? (
      <Form.Item
        style={{
          margin: 0,
        }}
        name={dataIndex}
        rules={[
          {
            required: true,
            message: `${title} is required.`,
          },
        ]}
      >
        <Input ref={inputRef} onPressEnter={save} onBlur={save} />
      </Form.Item>
    ) : (
      <div
        className="editable-cell-value-wrap"
        style={{
          paddingRight: 24,
        }}
        onClick={toggleEdit}
      >
        {children}
      </div>
    );
  }

  return <td {...restProps}>{childNode}</td>;
};

const Grid = () => {
  // HandsonTable 相关 ---------------------
  // HandsonTable 对象
  const hotTableComponent = useRef(null);
  // 初始化数据
  const initData = Handsontable.helper.createSpreadsheetData(20, 20);
  // HandsonTable 的 this 对象
  const [grid, setGrid] = useState(initData);
  // 表格的数据
  const [gridData, setGridData] = useState(initData);
  // 合并的单元格
  const [mergeCells, setMergeCells] = useState([
    { row: 9, col: 9, rowspan: 2, colspan: 2 },
  ]);
  // Copy 时的单元格背景色
  let copyColor;

  const setColor = (range, instance, className) => {
    console.log('setColor1', copyColor);
    const { start, end } = range[0];
    for (let { row } = start; row <= end.row; row += 1) {
      for (let { col } = start; col <= end.col; col += 1) {
        instance.setCellMeta(
          row,
          col,
          'className',
          `${className} htMiddle htCenter`
        );
        cell.push({
          row,
          col,
          className: `${className} htMiddle htCenter`,
        });
        setCell(cell);
      }
    }
    instance.render();
    instance.resumeRender();
    setGrid(instance);
  };

  // 记录单元格颜色
  const [cell, setCell] = useState([
    {
      row: 0,
      col: 5,
      className: 'red htMiddle htCenter',
    },
    {
      row: 0,
      col: 14,
      className: 'green htMiddle htCenter',
    },
    {
      row: 5,
      col: 0,
      className: 'yellow htMiddle htCenter',
    },
    {
      row: 5,
      col: 19,
      className: 'purple htMiddle htCenter',
    },
    {
      row: 14,
      col: 0,
      className: 'pink htMiddle htCenter',
    },
    {
      row: 14,
      col: 19,
      className: 'orange htMiddle htCenter',
    },
    {
      row: 19,
      col: 5,
      className: 'grey htMiddle htCenter',
    },
    {
      row: 19,
      col: 14,
      className: 'blue htMiddle htCenter',
    },
  ]);

  // HandsonTable 的 settings
  const [tableSettings, setTableSettings] = useState(() => {
    const initialState = {
      data: gridData,
      colHeaders: true,
      rowHeaders: true,
      manualColumnResize: true, // 列拖拽改变大小
      manualRowResize: true, // 行拖拽改变大小
      height: 'auto',
      colWidths: 40,
      rowHeights: 25,
      observeChanges: false,
      // copyable: true,
      mergeCells,
      afterChange(changes, source) {
        if (source === 'MergeCells') {
          console.log(changes);
          const row = changes[0][0];
          const col = changes[0][1];
          const lastIdx = changes.length - 1;
          const rowspan = changes[lastIdx][0] - row + 1;
          const colspan = changes[lastIdx][1] - col + 1;
          mergeCells.push({ row, col, rowspan, colspan });
          setMergeCells(mergeCells);
        }

        setGrid(this);
      },
      afterCopy(_, coords) {
        const { startRow, startCol } = coords[0];
        const color = this.getCellMeta(startRow, startCol).className;
        copyColor = color;
        console.log('afterCopy-copyColor', copyColor);
      },
      afterPaste(_, coords) {
        console.log('afterPaste-copyColor', copyColor);
        const { startRow, startCol, endRow, endCol } = coords[0];
        const range = [
          {
            start: { row: startRow, col: startCol },
            end: { row: endRow, col: endCol },
          },
        ];
        if (copyColor) {
          setColor(range, this, copyColor);
        }
        // copyColor = undefined
      },
      cell,
      // cells: (row, col, prop) => {
      //     console.log(row, col, prop)
      // },
      contextMenu: {
        items: {
          mergeCells: 'mergeCells',
          separator: Handsontable.plugins.ContextMenu.SEPARATOR,
          red: {
            name: '红色',
            callback(_, range) {
              setColor(range, this, 'red');
            },
          },
          green: {
            name: '绿色',
            callback(_, range) {
              setColor(range, this, 'green');
            },
          },
          yellow: {
            name: '黄色',
            callback(_, range) {
              setColor(range, this, 'yellow');
            },
          },
          purple: {
            name: '紫色',
            callback(_, range) {
              setColor(range, this, 'purple');
            },
          },
          pink: {
            name: '粉色',
            callback(_, range) {
              setColor(range, this, 'pink');
            },
          },
          orange: {
            name: '橙色',
            callback(_, range) {
              setColor(range, this, 'orange');
            },
          },
          grey: {
            name: '灰色',
            callback(_, range) {
              setColor(range, this, 'grey');
            },
          },
          blue: {
            name: '蓝色',
            callback(_, range) {
              setColor(range, this, 'blue');
            },
          },
          separator2: Handsontable.plugins.ContextMenu.SEPARATOR,
          clear: {
            name: '清除颜色',
            callback(_, range) {
              setColor(range, this, 'white');
            },
          },
        },
      },
      licenseKey: 'non-commercial-and-evaluation',
    };

    return initialState;
  });
  // HandsonTable 相关 结束 ---------------------

  // EditableProTable 相关 ---------------------
  const [tableData, setTableData] = useState([]);
  // EditableProTable 相关 结束 ---------------------

  // 记录地图总分
  const [totalScore, setTotalScore] = useState('0');
  // 是否允许执行 记录 功能
  const [recordFlag, setRecordFlag] = useState(false);

  /**
   * 遍历 HandsonTable 中的记录计算结果
   */
  const calculate = () => {
    let sum = 0;
    const result = {};
    const resultData = [];
    // console.log(grid.getCellMeta(0, 0)['className']);
    // console.log(grid.getDataAtCell(9, 10) || 0);
    // console.log("calculate", grid.getData(0, 5, 0, 5));

    for (let rowIndex = 0; rowIndex < 20; rowIndex += 1) {
      for (let colIndex = 0; colIndex < 20; colIndex += 1) {
        const color = grid
          .getCellMeta(rowIndex, colIndex)
          .className.split(' ')[0];
        const score = grid.getData(
          rowIndex,
          colIndex,
          rowIndex,
          colIndex
        )[0][0];

        if (color in result) {
          result[color] = result[color] + (Number(score) || 0);
        } else {
          result[color] = Number(score) || 0;
        }

        sum += Number(score) || 0;
      }
    }

    setTotalScore(sum);

    for (const key in result) {
      if (
        key !== 'undefined' &&
        key !== 'white' &&
        key !== 'htMiddle' &&
        key !== 'htCenter'
      ) {
        const currentData = tableData.filter((element) => {
          return element.color === key;
        });

        let guildName = key;
        let currentScore = 0;
        if (currentData.length > 0) {
          guildName = currentData[0].guildName;
          currentScore = Number(currentData[0].currentScore) || 0;
        }
        // console.log("currentData", currentData)
        const addScore = Number(result[key]) || 0;
        const afterScore = currentScore + result[key];
        resultData.push({
          color: key,
          guildName,
          currentScore,
          addScore,
          afterScore,
        });
      }
    }

    setRecordFlag(true);
    setTableData(resultData);

    // hotTableComponent.current.hotInstance.loadData([]);
  };

  /**
   * 下方 EditableProTable 字段定义
   */
  const originColumns = [
    {
      title: '公会名称',
      dataIndex: 'guildName',
      editable: true,
      width: '20%',
    },
    {
      title: '颜色',
      dataIndex: 'color',
      render: (text) => {
        return <StarTwoTone twoToneColor={text} />;
      },
      // editable: () => false,
    },
    // {
    //     title: '公会名称',
    //     dataIndex: 'guildName',
    // },
    {
      title: '当前分数',
      dataIndex: 'currentScore',
      editable: true,
      defaultSortOrder: 'descend',
      sorter: (a, b) => a.currentScore - b.currentScore,
      width: '20%',
    },
    {
      title: '本轮增加分数',
      dataIndex: 'addScore',
      editable: () => false,
      defaultSortOrder: 'descend',
      sorter: (a, b) => a.currentScore - b.currentScore,
    },
    {
      title: '本轮结算分数',
      dataIndex: 'afterScore',
      editable: () => false,
      defaultSortOrder: 'descend',
      sorter: (a, b) => a.afterScore - b.afterScore,
    },
  ];

  /**
   * 将 afterScore 赋值给 currentScore 并清空 afterScore
   */
  const record = () => {
    // console.log(tableData)
    if (!recordFlag) {
      message.warning({
        content: '请先计算后再记录',
        style: {
          marginTop: '50vh',
        },
      });
      return;
    }

    const result = tableData.map((element) => {
      return { ...element, currentScore: element.afterScore, afterScore: 0 };
    });
    // console.log(result)
    setTableData(result);
    setRecordFlag(false);
  };

  const importProps = {
    onChange: (info) => {
      const fileReader = new FileReader();
      fileReader.onload = (event) => {
        const { result } = event.target;
        const data = JSON.parse(result);

        const { savedGridData, savedMergeCells, savedCell, savedTableData } =
          data;

        // 设置 cell 的底色
        cell.splice(0, cell.length);
        savedCell.forEach((element) => {
          cell.push(element);
          grid.setCellMeta(
            element.row,
            element.col,
            'className',
            `${element.className} htMiddle htCenter`
          );
        });
        setCell(cell);

        // 设置 cell 的值
        for (let row = 0; row < 20; row += 1) {
          for (let col = 0; col < 20; col += 1) {
            gridData[row][col] = savedGridData[row][col];
          }
        }
        setGridData(gridData);

        // 设置 合并单元格
        console.log(mergeCells);
        console.log(savedMergeCells);
        mergeCells.splice(0, mergeCells.length);
        savedMergeCells.forEach((element) => {
          mergeCells.push(element);
        });
        setMergeCells(mergeCells);
        console.log(hotTableComponent);

        // 设置 计算结果
        setTableData(savedTableData);

        // 重新渲染
        grid.render();
        message.info({
          content: '文件读取成功',
          style: {
            marginTop: '50vh',
          },
        });
      };
      // 读取文件
      fileReader.readAsText(info.file);
    },
    showUploadList: false,
    accept: '.json',
    beforeUpload: () => false,
  };

  const exportData = () => {
    const str = JSON.stringify({
      savedGridData: gridData,
      savedMergeCells: mergeCells,
      savedCell: cell,
      savedTableData: tableData,
    });
    const blob = new Blob([str], {
      type: 'text/plain;charset=utf-8',
    });
    FileSaver.saveAs(blob, 'data.json');
  };

  const components = {
    body: {
      row: EditableRow,
      cell: EditableCell,
    },
  };

  const handleSave = (row) => {
    const newData = [...tableData];
    const index = newData.findIndex((item) => row.color === item.color);
    const item = newData[index];
    newData.splice(index, 1, { ...item, ...row });
    setTableData(newData);
  };

  const columns = originColumns.map((col) => {
    if (!col.editable) {
      return col;
    }

    return {
      ...col,
      onCell: (record) => ({
        record,
        editable: col.editable,
        dataIndex: col.dataIndex,
        title: col.title,
        handleSave,
      }),
    };
  });

  const [responsive, setResponsive] = useState(true);

  return (
    <>
      <Card
        title="编辑地图"
        extra={
          <Space>
            <Upload {...importProps}>
              <Button type="primary">导入</Button>
            </Upload>
            <Button type="primary" onClick={exportData}>
              导出
            </Button>
          </Space>
        }
      >
        <Row>
          <Col span={16}>
            <HotTable
              className="htMiddle htCenter"
              ref={hotTableComponent}
              settings={tableSettings}
            />
          </Col>
          <Col>
            <RcResizeObserver
              key="resize-observer"
              onResize={(offset) => {
                setResponsive(offset.width < 596);
              }}
            >
              <StatisticCard.Group>
                <StatisticCard
                  statistic={{
                    title: '地图总分',
                    tip: '地图上所有单元格的总分数',
                    value: totalScore,
                    suffix: '分',
                  }}
                />
                <Divider type={responsive ? 'horizontal' : 'vertical'} />
                <StatisticCard
                  statistic={{
                    title: '建议每轮增长分数(3家并列)',
                    tip: '地图总分 / 并列公会数',
                    value: Math.round(totalScore / 3),
                    suffix: '分',
                  }}
                />
                <StatisticCard
                  statistic={{
                    title: '建议每轮增长分数(4家并列)',
                    tip: '地图总分 / 并列公会数',
                    value: Math.round(totalScore / 4),
                    suffix: '分',
                  }}
                />
                <Divider type={responsive ? 'horizontal' : 'vertical'} />
              </StatisticCard.Group>
            </RcResizeObserver>
          </Col>
        </Row>
      </Card>
      <Card
        // style={{marginTop: 20}}
        title="结果计算"
        extra={
          <Space>
            <Button type="primary" onClick={calculate}>
              开始计算
            </Button>
            <Button type="primary" onClick={record}>
              记录
            </Button>
          </Space>
        }
      >
        <Table
          rowKey="color"
          components={components}
          rowClassName={() => 'editable-row'}
          bordered
          dataSource={tableData}
          columns={columns}
          pagination={false}
        />
      </Card>
    </>
  );
};

export default Grid;
